/*:
 * @plugindesc (v1.15)自定義滑鼠指針
 * @author 小c
 * @version 1.11
 * @date 11/30/2021
 *
 * @param Cursor List
 * @text 滑鼠指針列表
 * @type struct<cursorData>[]
 * @default []
 *
 * @param Cursor Z Index
 * @text 指針Z軸序號
 * @type number
 * @default 100
 *
 * @param Cursor Interval
 * @text 滑鼠指針更新時間
 * @type number
 * @min 1
 * @desc 滑鼠指針每次刷新的時間差，單位：幀
 * @default 10
 *
 * @param Default Cursor
 * @text 默認滑鼠指針
 * @desc 此處參數必須為滑鼠指針列表中的指針狀態名之一
 *
 * @param Scene Cursors
 * @text 場景-指針對應表
 * @type struct<sceneCursors>[]
 * @desc 指定場景的默認指針設定
 * @default []
 *
 * @param Battle Cursors
 * @text 戰鬥-指針對應表
 * @type struct<battleCursors>[]
 * @desc 指定戰鬥階段的默認指針設定，未設定時為Scene_Battle的場景指針
 * @default []
 *
 * @param Has Message Pause Cursor
 * @text 是否使用訊息等待指針
 * @type boolean
 * @on 使用
 * @off 不使用
 * @desc 如果不使用，【訊息框等待指針】將被忽略，此時訊息框觸發等待將不變換指針
 * @default false
 *
 * @param Message Pause Cursor
 * @text 訊息框等待指針
 * @desc 此處參數必須為滑鼠指針列表中的指針狀態名之一
 *
 * @param Battle Phase Test
 * @text 戰鬥phase測試開關
 * @type boolean
 * @desc 開發者在戰鬥中測試哪些流程phase未設定指針的開關，當設為true時，戰鬥中會在控制檯顯示沒有設定指針的phase
 * @default false
 *
 * @param Target Cursor
 * @text 戰鬥選擇目標滑鼠指針
 * @desc 此處參數必須為滑鼠指針列表中的指針狀態名之一
 *
 * @param Mouse Wait Count
 * @text 滑鼠最大靜止幀數
 * @type number
 * @min 1
 * @default 600
 * @desc 當滑鼠靜止不動一段時間後滑鼠消失，單位【幀】
 *
 * @param Custom Mouse Hidden Condition
 * @text 滑鼠隱藏額外條件
 * @type note
 * @default "condition = false;"
 * @desc JS代碼塊，布爾變量condition表示是否隱藏
 * 
 * @param Auto Execute Move Event
 * @text 是否自動觸發移動事件
 * @type boolean
 * @on 觸發
 * @off 不觸發
 * @desc 測試方法啟動遊戲不操作滑鼠【移動和點擊】，滑鼠若在正中間並迅速消失則為false，否則為true。測試時取false。
 * @default false
 *
 * @help 
 * 自定義滑鼠指針。
 * 使用方法：
 * 1. 將滑鼠指針png文件放入工程文件夾中你需要的位置
 * 2. 配置滑鼠指針列表
 * （1）首先定義一組滑鼠指針的狀態名
 * （2）文件URL指定精靈指針的png圖片，可以是幀動畫
 * 路徑以工程根目錄為當前目錄，舉例：img/system/cursors/a.png
 * 圖片幀動畫以橫向排列
 * （3）圖片幀數指定該幀動畫圖片的長度
 * （4）原點取值範圍[0, 1]，指定滑鼠精靈的原點anchor
 * 3. 默認指針參數填入一個指針狀態名，默認滑鼠即為該指針動畫
 * 4. 場景Scene與指針的對應關係配置中，場景Scene類名不可以是父類名
 * （比如Scene_MenuBase和Scene_File）
 * 類名對應關係
 * Scene_Title 封面
 * Scene_Map 地圖
 * Scene_Menu 主選單
 * Scene_Item 物品
 * Scene_Equip 裝備
 * Scene_Skill 技能
 * Scene_Status 人物狀態
 * Scene_Options 選項
 * Scene_Gameover 遊戲結束
 * Scene_Battle 戰鬥，此處是戰鬥默認值
 *
 * 戰鬥配置請設定【戰鬥-指針對應表】
 * 此對應表配置戰鬥流程和指針的對應關係
 * 戰鬥階段phase 一般有以下取值
 * input：戰鬥操作
 * turn：回合執行中
 * action：動作執行中
 * turnEnd：回合結束
 * 如果使用了YEP戰鬥核心，則是以下取值：
 * input：戰鬥操作
 * phaseChange：技能階段變更【技能執行中】
 * actionList：技能動作序列【技能執行中】
 * actionTargetList：技能目標序列【技能執行中】
 * 如果使用了YEP的ATB插件，則還有這個：
 * atb：ATB讀條過程中且沒有任何其他動作
 *
 * 當戰鬥流程沒有配置，滑鼠則是戰鬥默認值
 * 如果你不知道有哪些phase需要測試，請把【戰鬥phase測試開關】設定為true
 * 當開關為true時，戰鬥過程中按下F12，會在控制檯中顯示你沒有配置的phase
 * 測試完成後，請將開關重置為false
 *
 * 關於【訊息框等待指針】
 * 當事件中的【顯示文字】執行暫停時，如果使用訊息等待指針，指針將會變為
 * 指定的指針
 * 但執行事件操作【顯示選項】【數值輸入處理】【道具選擇處理】時將不執行
 * 變換
 *
 * JS函數
 * 用代碼修改滑鼠指針的方法
 * CP.CustomMouseCursor.setMouseCursorType(typeName) typeName為一個指針狀態名
 *
 * SceneManager.resetSceneMouseCursor() 重設滑鼠指針為當前Scene的指針
 * BattleManager.executeMouseCursorChanges() 重置滑鼠為當前戰鬥狀態（phase）
 * 的指針
 * $gameMap.currentMouseCursor() 返回當前地圖的正常滑鼠指針狀態名
 * 注意：這個函數取值可以動態改變！
 *
 * 關於【是否自動觸發移動事件】
 * 該插件參數需要測試一次才可以確定，測試條件為自身為false
 * 測試方法：啟動遊戲，不要操作滑鼠【包括移動和點擊都不要做】，如果滑鼠
 * 出現在中間且短時間後【大約是 滑鼠最大靜止幀數 的十分之一，如果 滑鼠
 * 最大靜止幀數 低於300幀，則為30幀】後直接消失，則該參數取值為false，若
 * 滑鼠指針偏移但不在準確座標上，亦為false，否則應為true
 *
 * 關於【滑鼠隱藏額外條件】
 * 該插件參數為一個JS代碼塊，控制布爾變量condition的取值，結果為true則強
 * 制隱藏滑鼠指針
 * 若滑鼠隱藏因該參數而起，滑鼠靜止時的計時將停止，該計時用於滑鼠不操作時
 * 的消失計時
 * 
 * 更新日誌
 * v1.00
 * 插件完成
 *
 * v1.01
 * 修復戰鬥測試結束會死機的問題
 * 添加戰鬥phase的測試開關
 *
 * v1.02
 * 滑鼠指針更新時間單位變更為幀
 * 增加滑鼠原點參數配置
 *
 * v1.03
 * 將地圖的指針刷新處理核心增加至本插件中
 *
 * v1.04
 * 大幅修改參數結構，引入精靈指針
 *
 * v1.05
 * 修復由單幀指針變成多幀指針時指針顯示錯誤的問題
 *
 * v1.06
 * 刪除參數指針，引入canvas指針
 * 場景變化時滑鼠可正常顯示
 * 二級URL參數已刪除
 *
 * v1.07
 * 增加滑鼠指針Z軸序列參數
 * 修復滑鼠在改變時會閃爍的問題
 *
 * v1.08
 * 修復程序錯誤時指針無法移動的BUG
 *
 * v1.09
 * 在遊戲啟動之後，滑鼠移動之前，可以通過點擊滑鼠將指針座標指向正確的
 * 位置。
 * 解決滑鼠指針消失後直接點擊滑鼠，指針不恢復顯示的問題
 *
 * v1.10
 * 遊戲開始時若玩家沒有操作滑鼠，滑鼠指針會很快消失
 * 消失幀數為【滑鼠最大靜止幀數】的十分之一與30幀的較大者
 * 增加一個屏蔽首次mousemove事件的插件參數，請根據測試結果設定
 *
 * v1.11
 * 追加顯示文字訊息框等待時的滑鼠指針變換
 *
 * v1.12
 * 追加滑鼠指針的額外隱藏條件
 * 更新到該版本時請及時確認插件參數
 *
 * v1.13
 * 修復戰鬥事件執行速度變快的問題
 *
 * v1.14
 * 修復视窗模式被拉伸之後滑鼠與實際座標發生偏差的問題
 *
 * v1.15
 * 修正戰鬥中選擇替換寵物時指針為戰鬥input指針
 * 此更新為針對CP_PetCore的補充
 */
/*~struct~sceneCursors:
 * @param sceneClass
 * @text Scene類名
 * @parent Object Selectors
 *
 * @param cursorName
 * @text 指針狀態名
 * @parent Object Selectors
 */
/*~struct~battleCursors:
 * @param phase
 * @text 戰鬥階段phase
 * @parent Object Selectors
 *
 * @param cursorName
 * @text 指針狀態名
 * @parent Object Selectors
 */
/*~struct~cursorData:
 * @param name
 * @text 指針狀態名
 * 
 * @param url
 * @text 文件URL
 *
 * @param frames
 * @text 圖片幀數
 * @type Number
 * @default 1
 *
 * @param anchorX
 * @text 原點X
 * @type number
 * @decimals 2
 * @min 0
 * @max 1
 * @desc 圖片原點的X比例
 * @default 0.50
 *
 * @param anchorY
 * @text 原點Y
 * @type number
 * @decimals 2
 * @min 0
 * @max 1
 * @desc 圖片原點的Y比例
 * @default 0.50
 */

var Imported = Imported || {};
Imported.CP_CustomMouseCursor = true;

var CP = CP || {};
CP.CustomMouseCursor = CP.CustomMouseCursor || {};
CP.CustomMouseCursor.Params = PluginManager.parameters("CP_CustomMouseCursor");

CP.CustomMouseCursor.getUrlData = function(url){
	var data = url.split("/");
	var name = data.pop().split(".")[0];
	var folder = data.join("/") + "/";
	return [folder, name];
};

CP.CustomMouseCursor.CURSOR_LIST = JSON.parse(CP.CustomMouseCursor.Params["Cursor List"]).map(function(cursorStr){
	var cursor = JSON.parse(cursorStr);
	cursor.frames = Number(cursor.frames) || 0;
	cursor.anchorX = Number(cursor.anchorX) || 0;
	cursor.anchorY = Number(cursor.anchorY) || 0;

	var data = this.getUrlData(cursor.url);
	cursor.bitmap = ImageManager.loadBitmap(data[0], data[1]);

	return cursor;
}.bind(CP.CustomMouseCursor));

CP.CustomMouseCursor.CURSOR_Z_INDEX = Number(CP.CustomMouseCursor.Params["Cursor Z Index"]) || 100; 
CP.CustomMouseCursor.CURSOR_INTERVAL = Number(CP.CustomMouseCursor.Params["Cursor Interval"]) || 10;
CP.CustomMouseCursor.DEFAULT_CURSOR = CP.CustomMouseCursor.Params["Default Cursor"];
CP.CustomMouseCursor.HAS_MESSAGE_PAUSE_CURSOR = eval(CP.CustomMouseCursor.Params["Has Message Pause Cursor"]) || false;
CP.CustomMouseCursor.MESSAGE_PAUSE_CURSOR = CP.CustomMouseCursor.Params["Message Pause Cursor"];

CP.CustomMouseCursor.SCENE_CURSORS = JSON.parse(CP.CustomMouseCursor.Params["Scene Cursors"]).map(function(item){
	return JSON.parse(item);
});

CP.CustomMouseCursor.BATTLE_CURSORS = JSON.parse(CP.CustomMouseCursor.Params["Battle Cursors"]).map(function(item){
	return JSON.parse(item);
});

CP.CustomMouseCursor.BATTLE_PHASE_TEST = eval(CP.CustomMouseCursor.Params["Battle Phase Test"]) || false;
CP.CustomMouseCursor.TARGET_CURSOR = CP.CustomMouseCursor.Params["Target Cursor"];

CP.CustomMouseCursor.MOUSE_WAIT_COUNT = Number(CP.CustomMouseCursor.Params["Mouse Wait Count"]) || 1;
CP.CustomMouseCursor.AUTO_EXECUTE_MOVE_EVENT = eval(CP.CustomMouseCursor.Params["Auto Execute Move Event"]) || false;
CP.CustomMouseCursor.CUSTOM_MOUSE_HIDDEN_CONDITION = new Function("condition"
	, JSON.parse(CP.CustomMouseCursor.Params["Custom Mouse Hidden Condition"]).trim() 
	+ "\nreturn condition;");

CP.CustomMouseCursor.setMousePosition = function(x, y){
	this._mouseRealX = x;
	this._mouseRealY = y;
};

CP.CustomMouseCursor.resetMousePosition = function(){
	var x = Math.round(Graphics.boxWidth / 2);
	var y = Math.round(Graphics.boxHeight / 2);
	this.setMousePosition(x, y);
	this.initMouseWaitCount();
};

CP.CustomMouseCursor.mouseX = function(){
	return this._mouseRealX;
};

CP.CustomMouseCursor.mouseY = function(){
	return this._mouseRealY;
};

CP.CustomMouseCursor.hideMouse = function(){
	document.body.style.cursor = "none";
};

CP.CustomMouseCursor.setMouseCursorType = function(typeName){
	this._cursorType = typeName;
};

CP.CustomMouseCursor.cursorType = function(){
	return this._cursorType;
};

CP.CustomMouseCursor.getMouseCursorData = function(){
	for(var i = 0; i < this.CURSOR_LIST.length; i++){
		var cursor = this.CURSOR_LIST[i];
		if(cursor.name === this._cursorType)
			return cursor;
	}

	return null;
};

CP.CustomMouseCursor.getMouseCursorBitmap = function(){
	var data = this.getMouseCursorData();
	return data ? data.bitmap : null;
};

CP.CustomMouseCursor.getMouseCursorFrame = function(){
	var data = this.getMouseCursorData();
	return !!data ? data.frames : 1;
};

CP.CustomMouseCursor.getMouseCursorAnchor = function(){
	var object = {x: 0, y: 0};
	var data = this.getMouseCursorData();
	if(!!data){
		object.x = data.anchorX;
		object.y = data.anchorY;
	}

	return object;
};

CP.CustomMouseCursor.refreshBattlePhase = function(){
	this._battlePhase = BattleManager._phase;
};

CP.CustomMouseCursor.isBattlePhaseNeedRefresh = function(){
	return this._battlePhase !== BattleManager._phase;
};

CP.CustomMouseCursor.initMouseWaitCount = function(){
	this._mouseWaitCount = Math.max(30, Math.floor(this.MOUSE_WAIT_COUNT / 10));
};

CP.CustomMouseCursor.resetMouseWaitCount = function(){
	this._mouseWaitCount = this.MOUSE_WAIT_COUNT;
};

CP.CustomMouseCursor.updateMouseWaitCount = function(){
	this._mouseWaitCount--;
	if(this._mouseWaitCount < -1)
		this._mouseWaitCount = -1;
};

CP.CustomMouseCursor.isMouseStop = function(){
	if(this._mouseWaitCount === undefined)
		this.initMouseWaitCount();
	return this._mouseWaitCount < 0;
};

//-----------------
// ImageManager
//-----------------
ImageManager.reserveMouseCursor = function(url, hue, smooth, reservationId){
	var data = CP.CustomMouseCursor.getUrlData(url);
	return this.reserveBitmap(data[0], data[1], hue, smooth, reservationId);
};

ImageManager.reserveAllMouse = function(){
	for(var i = 0; i < CP.CustomMouseCursor.CURSOR_LIST.length; i++){
		var data = CP.CustomMouseCursor.CURSOR_LIST[i];
		if(!!data.url){
			this.reserveMouseCursor(data.url, 0);
		}
	}
};

//-----------------
// Canvas_Mouse
//-----------------
function Canvas_Mouse(){
	this.initialize.apply(this, arguments);
};

Canvas_Mouse.prototype.initialize = function(x, y, width, height, id, zIndex){
	this._frameCount = 0; //幀計時
	this._currentFrame = 0; //當前幀序號
	this._maxFrame = 1; //動畫幀長度
	this._resizeRefresh = false; //拉屏時請求刷新的標識

	this.setupCanvas(width, height, id, zIndex);
	this.resetRect(x, y, width, height);
	Graphics._disableContextMenu(); //禁止右鍵選單

	this.show();
	this.setAnchor(0, 0);
	this.setupMouseBitmap();
	this.resetMouseFrameData();
	this.move(0, 0);
};

Canvas_Mouse.prototype.setupCanvas = function(width, height, id, zIndex){
	this._canvas = document.createElement("canvas");
	this._canvas.id = id;
	this._canvas.width = width;
	this._canvas.height = height;
	this._canvas.style.position = 'absolute';
    this._canvas.style.margin = 'auto';
	this._canvas.style.zIndex = zIndex;

	document.body.appendChild(this._canvas);
};

Canvas_Mouse.prototype.setupMouseBitmap = function(){
	this.setBitmap(CP.CustomMouseCursor.getMouseCursorBitmap());
};

Canvas_Mouse.prototype.resetRect = function(x, y, width, height){
	x = x || 0;
	y = y || 0;
	width = width || 0;
	height = height || 0;
	if(!this._rect)
		this._rect = new Rectangle(x, y, width, height);
	else{
		this._rect.x = x;
		this._rect.y = y; 
		this._rect.width = width;
		this._rect.height = height;
	}

	this.onWindowResize();
};

Canvas_Mouse.prototype.width = function(){
	return this._canvas.width;
};

Canvas_Mouse.prototype.height = function(){
	return this._canvas.height;
};

Canvas_Mouse.prototype.show = function(){
	this._hidden = false;
};

Canvas_Mouse.prototype.hide = function(){
	this._hidden = true;
};

Canvas_Mouse.prototype.isHidden = function(){
	if(this.customHiddenCondition())
		return true;
	return this._hidden;
};

//自定義隱藏條件
Canvas_Mouse.prototype.customHiddenCondition = function(){
	try{
		return CP.CustomMouseCursor.CUSTOM_MOUSE_HIDDEN_CONDITION.call(this, false);
	}catch(err){
		console.error(err);
		return false;
	}
};

Canvas_Mouse.prototype.setBitmap = function(bitmap){
	this._bitmap = bitmap;
};

Canvas_Mouse.prototype.move = function(x, y){
	this._x = x.clamp(0, this.width());
	this._y = y.clamp(0, this.height());
};

Canvas_Mouse.prototype.x = function(){
	var offsetX = 0;
	if(!!this.frame)
		offsetX = this._frame.width * this._anchorX;

	return this._x - offsetX;
};

Canvas_Mouse.prototype.y = function(){
	var offsetY = 0;
	if(!!this.frame)
		offsetY = this._frame.height * this._anchorY;

	return this._y - offsetY;
};

Canvas_Mouse.prototype.setFrame = function(x, y, width, height){
	if(!this._frame)
		this._frame = new Rectangle(x, y, width, height);
	else{
		this._frame.x = x;
		this._frame.y = y;
		this._frame.width = width;
		this._frame.height = height;
	}
};

Canvas_Mouse.prototype.frame = function(){
	return this._frame;
};

Canvas_Mouse.prototype.setAnchor = function(x, y){
	this._anchorX = x;
	this._anchorY = y;
};

Canvas_Mouse.prototype.context = function(){
	return this._canvas.getContext("2d");
};

Canvas_Mouse.prototype.clearRect = function(x, y, width, height){
	this.context().clearRect(x, y, width, height);
};

Canvas_Mouse.prototype.clear = function(){
	this.clearRect(0, 0, this.width(), this.height());
};

//強制請求滑鼠變化
Canvas_Mouse.prototype.resizeRefresh = function(){
	this._resizeRefresh = true;
};

Canvas_Mouse.prototype.onWindowResize = function() {
    var top = Graphics._canvas.offsetTop;
    var left = Graphics._canvas.offsetLeft;
    this._lastScale = Graphics._realScale;
    this._lastWindowWidth = document.body.clientWidth;
    this._lastWindowHeight = document.body.clientHeight;
    this._canvas.style.top = this._rect.y * this._lastScale + top + 'px';
    this._canvas.style.left = this._rect.x * this._lastScale + left + 'px';
    this._canvas.style.width = this._rect.width * this._lastScale + 'px';
    this._canvas.style.height = this._rect.height * this._lastScale + 'px';
    this._resizeRefresh = false;
};

Canvas_Mouse.prototype.isCanvasResizeNeeded = function(){
	return this._resizeRefresh || this._lastScale !== Graphics._realScale ||
    	this._lastWindowWidth !== document.body.clientWidth ||
   		this._lastWindowHeight !== document.body.clientHeight;
};

Canvas_Mouse.prototype.resetMouseFrameData = function(){
	this._frameCount = 0;
	this._currentFrame = 0;
	this._maxFrame = CP.CustomMouseCursor.getMouseCursorFrame();
	this.updateFrame();
};

Canvas_Mouse.prototype.refreshAnchor = function(){
	var anchor = CP.CustomMouseCursor.getMouseCursorAnchor();
	this.setAnchor(anchor.x, anchor.y);
};

Canvas_Mouse.prototype.isAnchorChanged = function(){
	var anchor = CP.CustomMouseCursor.getMouseCursorAnchor();
	return this._anchorX !== anchor.x || this._anchorY !== anchor.y;
};

Canvas_Mouse.prototype.update = function(){
	this.updateSize();
	this.updateBitmap();
	this.updateAnchor();
	this.updateFrameCount();
	this.updatePosition();
	this.updatePaint();
};

Canvas_Mouse.prototype.updateSize = function(){
	if(this.isCanvasResizeNeeded())
		this.onWindowResize();
};

Canvas_Mouse.prototype.updateBitmap = function(){
	if(this._bitmap !== CP.CustomMouseCursor.getMouseCursorBitmap()){
		this.setupMouseBitmap();
		this.resetMouseFrameData();
	}
};

Canvas_Mouse.prototype.updatePaint = function(){
	this.clear();
	if(!this.isHidden())
		this.drawBitmap();
};

Canvas_Mouse.prototype.drawBitmap = function(){
	var x = this.x();
	var y = this.y();
	var frame = this.frame();
	this.context().drawImage(this._bitmap._canvas, frame.x, frame.y, frame.width, frame.height, x, y, frame.width, frame.height);
};

Canvas_Mouse.prototype.updateFrameCount = function(){
	this._frameCount++;
	if(this._frameCount >= CP.CustomMouseCursor.CURSOR_INTERVAL)
		this.updateFrame();
};

Canvas_Mouse.prototype.updateFrame = function(){
	var width = Math.floor(this._bitmap.width / this._maxFrame);
	var height = this._bitmap.height;
	this.setFrame(width * this._currentFrame, 0, width, height);
	this._currentFrame = (this._currentFrame + 1) % this._maxFrame;
	this._frameCount = 0;
};

Canvas_Mouse.prototype.updateAnchor = function(){
	if(this.isAnchorChanged())
		this.refreshAnchor();
};

Canvas_Mouse.prototype.updatePosition = function(){
	var x = CP.CustomMouseCursor.mouseX();
	var y = CP.CustomMouseCursor.mouseY();
	this.move(x || 0, y || 0);
};

//-----------------
// Game_Map
//-----------------
Game_Map.prototype.currentMouseCursor = function(){
	return null;
};

CP.CustomMouseCursor.UPDATE_MAP = Game_Map.prototype.update;
Game_Map.prototype.update = function(sceneActive){
	CP.CustomMouseCursor.UPDATE_MAP.call(this, sceneActive);
	this.updateMapMouseCursor(sceneActive);
};

Game_Map.prototype.updateMapMouseCursor = function(sceneActive){
	if(sceneActive && !this.isEventRunning()){
		var cursor = this.currentMouseCursor();
		if(!!cursor)
			CP.CustomMouseCursor.setMouseCursorType(cursor);
		else
			SceneManager.resetSceneMouseCursor();
	}else if(this.isEventRunning())
		SceneManager.resetSceneMouseCursor();
};

//-----------------
// SceneManager
//-----------------
CP.CustomMouseCursor.INIT_SCENE_MANAGER = SceneManager.initialize;
SceneManager.initialize = function(){
	CP.CustomMouseCursor.INIT_SCENE_MANAGER.call(this);
	CP.CustomMouseCursor.resetMousePosition();
};

CP.CustomMouseCursor.GOTO_SCENE = SceneManager.goto;
SceneManager.goto = function(sceneClass){
	CP.CustomMouseCursor.GOTO_SCENE.call(this, sceneClass);
	if(!!sceneClass)
		this.changeSceneMouseCursor(sceneClass);
};

SceneManager.sceneCursor = function(sceneClass){
	var className = sceneClass.name;
	for(var i = 0; i < CP.CustomMouseCursor.SCENE_CURSORS.length; i++){
		var cursor = CP.CustomMouseCursor.SCENE_CURSORS[i];
		if(cursor.sceneClass == sceneClass.name)
			return cursor.cursorName;
	}

	return CP.CustomMouseCursor.DEFAULT_CURSOR;
};

SceneManager.changeSceneMouseCursor = function(sceneClass){
	var cursor = this.sceneCursor(sceneClass);
	CP.CustomMouseCursor.setMouseCursorType(cursor);
};

SceneManager.resetSceneMouseCursor = function(){
	this.changeSceneMouseCursor(this._scene.constructor);
};

CP.CustomMouseCursor.STOP_GAME_SCENE = SceneManager.stop;
SceneManager.stop = function(){
    CP.CustomMouseCursor.STOP_GAME_SCENE.call(this);
    this.requestUpdate(); //死機時需要繼續啟動循環
};

CP.CustomMouseCursor.REQUEST_SCENE_UPDATE = SceneManager.requestUpdate;
SceneManager.requestUpdate = function(){
	if(this._stopped)
		requestAnimationFrame(this.updateMouseCanvasWhenGameStop.bind(this)); //死機的時候修改為死機循環
	else
		CP.CustomMouseCursor.REQUEST_SCENE_UPDATE.call(this);
};

CP.CustomMouseCursor.UPDATE_ALL_SCENE = SceneManager.update;
SceneManager.update = function(){
	CP.CustomMouseCursor.UPDATE_ALL_SCENE.call(this);
	
	if(!Utils.isMobileDevice()){
		this.updateMouseCanvas();
		if(!!this._mouseCanvas && !this._mouseCanvas.customHiddenCondition())
			CP.CustomMouseCursor.updateMouseWaitCount();
	}
};

SceneManager.updateMouseCanvas = function(){
	if(!this._mouseCanvas)
		this._mouseCanvas = new Canvas_Mouse(0, 0, Graphics.boxWidth, Graphics.boxHeight, "MouseCanvas"
			, CP.CustomMouseCursor.CURSOR_Z_INDEX);
	this._mouseCanvas.update();
	if(CP.CustomMouseCursor.isMouseStop())
		this.hideMouse();
};

//死機時循環
SceneManager.updateMouseCanvasWhenGameStop = function(){
	if(!Utils.isMobileDevice()){
		this.updateMouseCanvas();
		CP.CustomMouseCursor.updateMouseWaitCount();
	}
	this.requestUpdate();
};

SceneManager.hideMouse = function(){
	if(!!this._mouseCanvas)
		this._mouseCanvas.hide();
	TouchInput.setMovedFlag();
};

SceneManager.showMouse = function(){
	if(!!this._mouseCanvas)
		this._mouseCanvas.show();
};

SceneManager.moveMouse = function(x, y){
	CP.CustomMouseCursor.setMousePosition(x, y);
};

//刷新滑鼠尺寸範圍，视窗變更執行
SceneManager.resizeMouseRefresh = function(){
	if(this._mouseCanvas)
		this._mouseCanvas.resizeRefresh();
};

//-----------------
// BattleManager
//-----------------
CP.CustomMouseCursor.BATTLE_INIT_MEMBERS = BattleManager.initMembers;
BattleManager.initMembers = function(){
	CP.CustomMouseCursor.BATTLE_INIT_MEMBERS.call(this);
	this._showBattleMouseCursor = false; //顯示戰鬥場景默認圖示
};

CP.CustomMouseCursor.UPDATE_BATTLE_EVENT = BattleManager.updateEvent;
BattleManager.updateEvent = function(){
	if(CP.CustomMouseCursor.UPDATE_BATTLE_EVENT.call(this)){
		this._showBattleMouseCursor = true;
		return true;
	}else
		return false;
};

CP.CustomMouseCursor.UPDATE_BATTLE = BattleManager.update;
BattleManager.update = function(){
	CP.CustomMouseCursor.UPDATE_BATTLE.call(this);
	if(this._showBattleMouseCursor)
		SceneManager.resetSceneMouseCursor();
	else
		this.updateMouseCursor();
	this._showBattleMouseCursor = false;
};

BattleManager.updateMouseCursor = function(){
	if(CP.CustomMouseCursor.isBattlePhaseNeedRefresh()){
		this.executeMouseCursorChanges();
		CP.CustomMouseCursor.refreshBattlePhase();
	}
};

BattleManager.executeMouseCursorChanges = function(){
	var cursor = this.getPhaseCursor();
	if(!!cursor)
		CP.CustomMouseCursor.setMouseCursorType(cursor);
	else if(!!this._phase){
		if(CP.CustomMouseCursor.BATTLE_PHASE_TEST)
			console.log(this._phase);
		SceneManager.resetSceneMouseCursor();
	}
};

BattleManager.getPhaseCursor = function(){
	for(var i = 0; i < CP.CustomMouseCursor.BATTLE_CURSORS.length; i++){
		var cursor = CP.CustomMouseCursor.BATTLE_CURSORS[i];
		if(cursor.phase == BattleManager._phase)
			return cursor.cursorName;
	}

	return null;
};

//-----------------
// TouchInput
//-----------------
CP.CustomMouseCursor.INIT_TOUCH_INPUT = TouchInput.initialize;
TouchInput.initialize = function(){
	//說明
	//由於測試環境中，遊戲啟動後會自動觸發一次mousemove事件但座標是不準確的
	//因此第一次mousemove事件會被手動屏蔽
	//插件參數【是否自動觸發移動事件】決定是否執行這個手動屏蔽
	this._hasMoved = !CP.CustomMouseCursor.AUTO_EXECUTE_MOVE_EVENT;
	CP.CustomMouseCursor.INIT_TOUCH_INPUT.call(this);
};

TouchInput.setMovedFlag = function(){
	this._hasMoved = true;
};

CP.CustomMouseCursor.ON_MOUSE_MOVE = TouchInput._onMouseMove;
TouchInput._onMouseMove = function(event){
    CP.CustomMouseCursor.ON_MOUSE_MOVE.call(this, event);
    if(this._hasMoved)
    	this.changeMousePosition(event);
    else
    	this.setMovedFlag();
};

CP.CustomMouseCursor.ON_MOUSE_DOWN = TouchInput._onMouseDown;
TouchInput._onMouseDown = function(event){
	CP.CustomMouseCursor.ON_MOUSE_DOWN.call(this, event);
	this.setMovedFlag();
	this.changeMousePosition(event);
};

TouchInput.changeMousePosition = function(event){
	var x = Graphics.pageToCanvasX(event.pageX);
    var y = Graphics.pageToCanvasY(event.pageY);

    CP.CustomMouseCursor.setMousePosition(x, y);
    CP.CustomMouseCursor.resetMouseWaitCount();
    SceneManager.showMouse();
};

//-----------------
// Graphics
//-----------------
CP.CustomMouseCursor.GRAPHICS_ON_WINDOW_RESIZE = Graphics._onWindowResize;
Graphics._onWindowResize = function(){
	CP.CustomMouseCursor.GRAPHICS_ON_WINDOW_RESIZE.call(this);
	SceneManager.resizeMouseRefresh();
};

//-----------------
// Scene_Base
//-----------------
Scene_Base.prototype.isMessageWindowPaused = function(){
	if(!CP.CustomMouseCursor.HAS_MESSAGE_PAUSE_CURSOR)
		return false;
	if(!this._messageWindow)
		return false;
	else if(!this._messageWindow.pause)
		return false;
	return this.isAnyMessageSubWindowActive();
};

Scene_Base.prototype.isAnyMessageSubWindowActive = function(){
	return true;
};

CP.CustomMouseCursor.SCENE_BASE_UPDATE = Scene_Base.prototype.update;
Scene_Base.prototype.update = function(){
	CP.CustomMouseCursor.SCENE_BASE_UPDATE.call(this);
	this.updateMessageSubWindowMouseCursor();
};

Scene_Base.prototype.updateMessageSubWindowMouseCursor = function(){
	if(this.isMessageWindowPaused())
		CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.MESSAGE_PAUSE_CURSOR);
};

//-----------------
// Scene_Boot
//-----------------
CP.CustomMouseCursor.BOOT_LOAD_SYSTEM_IMAGES = Scene_Boot.loadSystemImages;
Scene_Boot.loadSystemImages = function(){
	CP.CustomMouseCursor.BOOT_LOAD_SYSTEM_IMAGES.call(this);
	ImageManager.reserveAllMouse();
};

//-----------------
// Scene_Battle
//-----------------
CP.CustomMouseCursor.BATTLE_COMMAND_ATTACK = Scene_Battle.prototype.commandAttack;
Scene_Battle.prototype.commandAttack = function(){
	CP.CustomMouseCursor.BATTLE_COMMAND_ATTACK.call(this);
	CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.TARGET_CURSOR);
};

CP.CustomMouseCursor.ON_BATTLE_SKILL_OK = Scene_Battle.prototype.onSkillOk;
Scene_Battle.prototype.onSkillOk = function(){
    CP.CustomMouseCursor.ON_BATTLE_SKILL_OK.call(this);
    this.setActionOkCursor();
};

CP.CustomMouseCursor.ON_BATTLE_ITEM_OK = Scene_Battle.prototype.onItemOk;
Scene_Battle.prototype.onItemOk = function() {
    CP.CustomMouseCursor.ON_BATTLE_ITEM_OK.call(this);
    this.setActionOkCursor();
};

Scene_Battle.prototype.setActionOkCursor = function(){
	if(Imported.CP_PetCore && this._changePetWindow.isOpenAndActive())
		BattleManager.executeMouseCursorChanges();
	else
		CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.TARGET_CURSOR);
};

CP.CustomMouseCursor.ON_BATTLE_ACTOR_OK = Scene_Battle.prototype.onActorOk;
Scene_Battle.prototype.onActorOk = function(){
	CP.CustomMouseCursor.ON_BATTLE_ACTOR_OK.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ACTOR_CANCEL = Scene_Battle.prototype.onActorCancel;
Scene_Battle.prototype.onActorCancel = function(){
	CP.CustomMouseCursor.ON_BATTLE_ACTOR_CANCEL.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ENEMY_OK = Scene_Battle.prototype.onEnemyOk;
Scene_Battle.prototype.onEnemyOk = function(){
	CP.CustomMouseCursor.ON_BATTLE_ENEMY_OK.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ENEMY_CANCEL = Scene_Battle.prototype.onEnemyCancel;
Scene_Battle.prototype.onEnemyCancel = function(){
	CP.CustomMouseCursor.ON_BATTLE_ENEMY_CANCEL.call(this);
	BattleManager.executeMouseCursorChanges();
};

//-----------------
// 主程序
//-----------------
if(!Utils.isMobileDevice())
	CP.CustomMouseCursor.hideMouse();
CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.DEFAULT_CURSOR);